<?php
namespace ZyucMini\Core;

use ZyucMini\Core\Dir;

/**
 * 视图类 - 负责模板渲染和输出
 * 支持layout嵌套、直接输出模板、设置模板变量
 * 使用ob_start相关方法优化输出缓冲
 */

class View
{
    /**
     * 模板变量存储
     * @var array
     */
    private $variables = [];
    
    /**
     * 模板文件路径
     * @var string
     */
    private $templatePath = '';
    
    /**
     * 布局文件路径
     * @var string
     */
    private $layoutPath = '';
    
    /**
     * 模板文件扩展名
     * @var string
     */
    private $templateExtension = '.php';
    
    /**
     * 构造函数
     * @param string $templatePath 模板文件基础路径
     */
    public function __construct($templatePath)
    {
        if (!Dir::exists($templatePath)) {
            throw new \Exception("ZyucMini\Core\View Error: template directory not found: $templatePath");
        }
        $this->templatePath = $templatePath;
    }
    
    /**
     * 设置模板变量
     * @param string|array $key 变量名或变量数组
     * @param mixed $value 变量值
     * @return View
     */
    public function assign($key, $value = null)
    {
        if (is_array($key)) {
            $this->variables = array_merge($this->variables, $key);
        } else {
            $this->variables[$key] = $value;
        }
        return $this;
    }
    
    /**
     * 获取模板变量
     * @param string $key 变量名
     * @param mixed $default 默认值
     * @return mixed
     */
    public function get($key, $default = null)
    {
        return isset($this->variables[$key]) ? $this->variables[$key] : $default;
    }
    
    /**
     * 渲染模板内容（内部方法）
     * @param string $template 模板文件名（不含扩展名）
     * @param array $variables 额外变量
     * @return string
     */
    private function renderTemplate($template, $variables = [])
    {
        // 合并变量
        $allVariables = array_merge($this->variables, $variables);
        
        // 开始输出缓冲
        ob_start();
        
        // 提取变量到当前作用域
        extract($allVariables, EXTR_SKIP);
        
        // 包含模板文件
        $templateFile = $this->templatePath . $template . $this->templateExtension;
        if (file_exists($templateFile)) {
            include $templateFile;
        } else {
            echo "模板文件不存在: " . $templateFile;
        }
        
        // 获取缓冲内容
        $content = ob_get_clean();
        
        return $content;
    }
    
    /**
     * 设置布局文件
     * @param string $layout 布局文件名（不含扩展名）
     * @return View
     */
    public function layout($layout)
    {
        $this->layoutPath = $layout;
        return $this;
    }
    
    /**
     * 渲染并输出模板
     * 如果设置了布局文件，则自动使用布局嵌套；否则直接输出模板
     * @param string $template 模板文件名（不含扩展名）
     * @param array $variables 额外变量
     * @return void
     */
    public function display($template, $variables = [])
    {
        // 渲染主模板内容
        $content = $this->renderTemplate($template, $variables);
        
        // 如果没有设置布局，直接输出内容
        if (empty($this->layoutPath)) {
            echo $content;
            return;
        }
        
        // 使用布局嵌套输出
        ob_start();
        
        // 提取变量到当前作用域，并设置content变量
        $allVariables = array_merge($this->variables, $variables, ['content' => $content]);
        extract($allVariables, EXTR_SKIP);
        
        // 包含布局文件
        $layoutFile = $this->templatePath . $this->layoutPath . $this->templateExtension;
        if (file_exists($layoutFile)) {
            include $layoutFile;
        } else {
            echo "布局文件不存在: " . $layoutFile;
        }
        
        // 输出缓冲内容
        echo ob_get_clean();
    }
    
    /**
     * 设置模板文件基础路径
     * @param string $path 路径
     * @return View
     */
    public function setTemplatePath($path)
    {
        $this->templatePath = rtrim($path, '/') . '/';
        return $this;
    }
    
    /**
     * 设置模板文件扩展名
     * @param string $extension 扩展名
     * @return View
     */
    public function setTemplateExtension($extension)
    {
        $this->templateExtension = $extension;
        return $this;
    }
    
    /**
     * 获取模板文件基础路径
     * @return string
     */
    public function getTemplatePath()
    {
        return $this->templatePath;
    }
    
    /**
     * 清空所有模板变量
     * @return View
     */
    public function clear()
    {
        $this->variables = [];
        return $this;
    }
}
